package monitor

import (
	"fmt"
	"github.com/astaxie/beego/logs"
	"time"
	"cloud_worm/util/umodels/mysqldb"
	"cloud_worm/util/umodels/mysqldb/dbmanager"
	"cloud_worm/wormweb/controllers/ctrconfig"
	"cloud_worm/util/proto/urpc"
	"cloud_worm/wormweb/controllers/ctrutil"
)

const (
	FileMonitorConfigVersion = 100100104
	CmdMonitorConfigVersion = 100100104
	LogCollectorConfigVersion = 100100104
)

type NotifyAutoConfig struct {
	AccessSrv       string
	AgentID 		string
	AgentIP 		string
	NotifyType 		int
	PayLoad 		[]byte
}

// fast queue/async queue
func (n * NotifyAutoConfig) Done()  {
	args := urpc.AutoConfigArgs{
		AgentID: n.AgentID,
		AgentIP: n.AgentIP,
		NotifyType: n.NotifyType,
		PayLoad: n.PayLoad,
	}
	reply := urpc.AutoConfigReply{}

	if n.AccessSrv == "" {
		worm := &dbmanager.WormId{AgentId: n.AgentID, IP: n.AgentIP}
		if err := worm.Read("agent_id", "ip"); err != nil {
			// 正常这里不应该失败，所以必须采用重试机制
			time.Sleep(500 * time.Microsecond)
			if err := worm.Read("agent_id", "ip"); err != nil {
				time.Sleep(1 * time.Second)
				if err := worm.Read("agent_id", "ip"); err != nil {
					time.Sleep(2 * time.Second)
					if err := worm.Read("agent_id", "ip"); err != nil {
						// TODO：xxxx
						logs.Info(fmt.Sprintf("agent'%s' not online error: %s", n.AgentIP, err.Error()))
						return
					}
				}
			}
		}
		n.AccessSrv = worm.ServerAddr
	}

	rpcAddr, _ := ctrutil.GetRpcIDForAccessSrv(n.AccessSrv)
	err := ctrutil.AccessSrvRpc.Call(rpcAddr, "AutoConfig.DealAutoConfig", &args, &reply)
	if err != nil {
		logs.Error(fmt.Sprintf("NotifyAutoConfig %s", err.Error()))
	}
	logs.Debug(fmt.Sprintf("NotifyAutoConfig rpc call: %v", args))

	return
}

// slow queue/sync queue
func (n * NotifyAutoConfig) Doing()  {
	if AutoConfigForOnline == false {
		return
	}
	time.Sleep(5 * time.Second)

	args := urpc.AutoConfigArgs{
		AgentID: n.AgentID,
		AgentIP: n.AgentIP,
		NotifyType: n.NotifyType,
		PayLoad: n.PayLoad,
	}
	reply := urpc.AutoConfigReply{}

	if n.AccessSrv == "" {
		worm := &dbmanager.WormId{AgentId: n.AgentID, IP: n.AgentIP}
		if err := worm.Read("agent_id", "ip"); err != nil {
			// 正常这里不应该失败，所以必须采用重试机制
			time.Sleep(500 * time.Microsecond)
			if err := worm.Read("agent_id", "ip"); err != nil {
				time.Sleep(1 * time.Second)
				if err := worm.Read("agent_id", "ip"); err != nil {
					time.Sleep(2 * time.Second)
					if err := worm.Read("agent_id", "ip"); err != nil {
						// TODO：xxxx
						logs.Info(fmt.Sprintf("agent'%s' not online error: %s", n.AgentIP, err.Error()))
						return
					}
				}
			}
		}
		n.AccessSrv = worm.ServerAddr
	}

	rpcAddr, _ := ctrutil.GetRpcIDForAccessSrv(n.AccessSrv)
	err := ctrutil.AccessSrvRpc.Call(rpcAddr, "AutoConfig.DealAutoConfig", &args, &reply)
	if err != nil {
		logs.Error(fmt.Sprintf("NotifyAutoConfig %s", err.Error()))
	}
	logs.Debug(fmt.Sprintf("NotifyAutoConfig rpc call: %v", args))

	return
}

var AutoConfigForOnline = false

const AutoConfigForOnlineName = "auto_config_for_online"

// 加载配置
func AutoConfigForOnlineLoad() error {
	conf := &dbmanager.WebConfig{Name: AutoConfigForOnlineName}
	if err := conf.Read("name"); err == nil {
		switch conf.Value {
		case "1", "t", "T", "true", "TRUE", "True", "YES", "yes", "Yes", "Y", "y", "ON", "on", "On":
			AutoConfigForOnline = true
		case "0", "f", "F", "false", "FALSE", "False", "NO", "no", "No", "N", "n", "OFF", "off", "Off":
			AutoConfigForOnline = false
		default:
			return fmt.Errorf("config value format error")
		}
	} else {
		return fmt.Errorf("读WebConfig(%s)错误: %s", AutoConfigForOnlineName, err.Error())
	}

	logs.Info(fmt.Sprintf("set %s=%v", AutoConfigForOnlineName, AutoConfigForOnline))

	return nil
}

func init() {
	ctrconfig.RegisterConfigLoad(AutoConfigForOnlineName, AutoConfigForOnlineLoad)

	// 尝试创建该列数据
	conf := &dbmanager.WebConfig{Name: AutoConfigForOnlineName}
	if err := conf.Read("name"); err != nil {
		conf.Commit = "agent上线Config"
		conf.Type = dbmanager.BoolValue
		conf.Value = "false"
		conf.Created = time.Now().Unix()
		conf.Updated = conf.Created
		conf.Status = mysqldb.StatusValid
		conf.Insert()
	}

	AutoConfigForOnlineLoad()
}